package cn.com.cfae.iras.doc.analyze.parse;

import cn.com.cfae.iras.doc.analyze.parse.kv.TextLayout;
import cn.com.cfae.iras.doc.analyze.parse.model.*;
import cn.com.cfae.iras.doc.analyze.parse.model.table.BaseTable;
import cn.com.cfae.iras.doc.analyze.parse.model.table.TableItem;
import cn.com.cfae.iras.doc.analyze.parse.tokenizer.FXRTokenizer;
import cn.com.cfae.iras.doc.analyze.pdf.PdfExtractor;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import io.netty.util.internal.StringUtil;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.lang3.StringUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class PDFBaseParser {

    public BaseTable getBaseTable() {
        return baseTable;
    }

    public DocumentModel parse(File pdfFile, TableType tableType) {
        return parse(pdfFile, tableType, null);
    }

    public DocumentModel parse(File pdfFile, TableType tableType, IndustryType industryType) {
        return null;
    }

    private SimilarAnalyser similarAnalyser = SimilarAnalyser.getInstance();

    private BaseTable baseTable = null;


    private FXRTokenizer fxrTokenizer = FXRTokenizer.getInstance();

    public void setBaseTable(BaseTable baseTable) {
        this.baseTable = baseTable;
    }

    private static Logger logger = LoggerFactory.getLogger(PDFBaseParser.class);

    private List<String> commandLine(String[] args) throws Exception {
        CommandLineParser parser = new DefaultParser();
        CommandLine cmd = parser.parse(PdfExtractor.buildOptions(), args);
        return new PdfExtractor(cmd).extractTables(cmd);
    }

    /**
     * 抽取整个PDF表格内容数据
     *
     * @param args
     * @return
     * @throws Exception
     */
    private List<List<String>> commandLine2(String[] args) throws Exception {
        CommandLineParser parser = new DefaultParser();
        CommandLine cmd = parser.parse(PdfExtractor.buildOptions(), args);
        return new PdfExtractor(cmd).extractTables2(cmd);
    }


    protected List<String> extractPdfByText(String[] args) throws Exception {
        return commandLine(args);

    }

    protected List<List<String>> extractPdfAllTables(String[] args) throws Exception {
        return commandLine2(args);
    }


    protected List<String> extractPdfByTable(String[] args) throws Exception {
        return commandLine(args);
    }

    protected PDDocument loadPDDocument(File pdfFile) {
        PDDocument pdDocument = null;
        try {
            pdDocument = PDDocument.load(pdfFile);

        } catch (IOException e) {
            logger.error(e.getMessage(), e);
        } finally {

        }
        return pdDocument;
    }


    @Deprecated
    protected int getTotalPageNumber(File pdfFile) {
        PDDocument pdDocument = null;
        int totalNumberPage = 0;
        try {
            pdDocument = PDDocument.load(pdfFile);
            totalNumberPage = pdDocument.getNumberOfPages();
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (pdDocument != null) {
                try {
                    pdDocument.close();
                } catch (IOException e) {
                    logger.error(e.getMessage(), e);
                }
            }
        }
        return totalNumberPage;
    }

    protected void closeDocument(PDDocument pdDocument) {
        if (pdDocument != null) {
            try {
                pdDocument.close();
            } catch (IOException e) {
                logger.error(e.getMessage(), e);
            } finally {
            }
        }
    }

    /**
     * TODO  待添加逻辑，相似度阈值设置需要调整
     *
     * @param text
     * @return
     */
    protected TableItem getTableItem(String text) {
        long t1 = System.currentTimeMillis();
        logger.info("开始分析章节标题对应的表格体系目录标题......");
        double minSimilarityThreshold = ISimilarityThreshold.CATALOG_SIMILARITY_THRESHOLD;
        TableItem target = null;
        List<String> synonyms = getBaseTable().getSynonyms();
        fxrTokenizer.loadCoreSynonyms(synonyms);
        List<String> wordList = fxrTokenizer.splitWords(text);
        for (String word : wordList) {
            for (TableItem tableItem : getBaseTable().getTableItemList()) {
                if (tableItem.getSynonyms().contains(word)) {
                    target = tableItem;
                    break;
                }
                if (target == null) {
                    for (String itemName : tableItem.getSynonyms()) {
                        double similarity = similarAnalyser.similarity(text, itemName);
                        if (similarity >= minSimilarityThreshold) {
                            target = tableItem;
                            break;
                        }
                    }
                }
                if (target != null) {
                    logger.info("分析章节标题，分析章节标题：{}对应表格体系目录完成，匹配到的目录标题：{}。", text, target.getItemName());
                    break;
                }
            }
        }

        List<String> filters = getBaseTable().getFilters();
        if (filters.contains(target.getItemNo())) {
            logger.warn("分析章节标题，根据章节标题：{}获取表格体系目录完成，该表格体系需被过滤掉！！！");
            return null;
        }
        fxrTokenizer.unloadCoreSynonyms(synonyms);
        long t2 = System.currentTimeMillis();
        logger.info("分析章节标题，根据章节标题：{}获取表格体系目录标题完成，匹配结果：{}，匹配到的表格体系目录标题：{}，耗时：{}毫秒。", text, target == null ? false : true, target == null ? null : target.getItemName(), (t2 - t1));
        return target;
    }

    protected TextLayout createKVTextLayout(JsonObject jsonObject) {
        double top = jsonObject.get("top").getAsDouble();
        if (top == 0) {
            return null;
        }
        double left = jsonObject.get("left").getAsDouble();
        double height = jsonObject.get("height").getAsDouble();
        double width = jsonObject.get("width").getAsDouble();
        return new TextLayout(jsonObject.get("text").getAsString(), top, left, height, width);
    }

    protected TableItem getTableSubItem(String text) {
        long t1 = System.currentTimeMillis();
        logger.info("根据章节标题获取表格体系目录......");
        double minSimilarityThreshold = ISimilarityThreshold.CATALOG_SIMILARITY_THRESHOLD;
        TableItem target = null;
        for (TableItem tableItem : getBaseTable().getTableItemList()) {
            for (String synonym : tableItem.getSynonyms()) {
                double similarity = similarAnalyser.similarity(text, synonym);
                if (similarity >= minSimilarityThreshold) {
                    target = tableItem;
                    logger.info("根据章节标题获取表格体系目录完成，匹配到的目录标题：{}。", target.getItemName());
                    break;
                }
            }
            if (target != null) {
                break;
            }
        }
        long t2 = System.currentTimeMillis();
        logger.info("根据章节标题获取表格体系目录完成，匹配结果：{}，匹配到的目录标题：{}，耗时：{}毫秒。", target == null ? false : true, target == null ? null : target.getItemName(), (t2 - t1));
        return target;
    }

    protected String combineTextJsonArray(JsonArray jsonArray) {
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < jsonArray.size(); i++) {
            String text = jsonArray.get(i).getAsJsonObject().get("text").getAsString();
            if (StringUtils.isEmpty(text)) {
                continue;
            }
            stringBuilder.append(text);
        }
        return stringBuilder.toString();
    }


    protected int getPageModelBottomPageNum(PageModel pageModel) {
        JsonArray jsonArray = pageModel.getJsonTextData().getAsJsonArray().get(0).getAsJsonObject().get("data").getAsJsonArray();
        String text = combineTextJsonArray(jsonArray.get(jsonArray.size() - 1).getAsJsonArray());
        if (StringUtils.isEmpty(text)) {
            return 0;
        }
        text = text.replaceAll("\\s{0,}", "");
        String regex = "\\d{1,3}";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(text);
        if (matcher.matches()) {
            return Integer.parseInt(text);
        } else {
            return 0;
        }
    }
}
